洛谷 P4766 [CERC2014]Outer space invaders 题解

Description

有 $n$ 个外星人进攻,第 $i$ 个外星出现时间为 $a_i$ ,距离为 $d_i$ ,必须在时间 $b_i$ 前被消灭。

你的武器可以设置任何给定的功率。如果被设置了功率 $R$,它会摧毁距离在 $R$ 及以内的所有外星人,同时消耗 $R$ 单位的燃料。

求存活条件下最少要消耗多少燃料。

数据范围:$n<=300 , 1<=a_i<b_i<=10000 , 1<=d_i<=10000$

Solution

设 $f[i][j]$ 为消灭 $i–j$ 时间内外星人的最少花费。设这段区间最晚出现的外星人编号为 $id$,则转移方程为:

$f[i][j]=min(f[i][j],f[i][k-1]+a[id].d+f[k+1][j])$

如果开二维数组,$10000$ 有点太大。题面只出现了 $300$ 个外星人,可以离散化。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 50005;
struct node
{
int l, r, d;
} a[maxn];
int T, n, m, t[maxn], cnt, f[700][700];

void solve()
{
cnt = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].d);
t[++cnt] = a[i].l;
t[++cnt] = a[i].r;
}
sort(t + 1, t + cnt + 1);
m = unique(t + 1, t + cnt + 1) - t - 1;
for(int i = 1; i <= n; i++)
{
a[i].l = lower_bound(t + 1, t + m + 1, a[i].l) - t;
a[i].r = lower_bound(t + 1, t + m + 1, a[i].r) - t;
}
for(int i = 0; i <= m; i++)
for(int l = 1; l + i <= m; l++)
{
int r = l + i, id = 0;
for(int j = 1; j <= n; j++)
if(a[j].l >= l && a[j].r <= r && (!id || a[j].d > a[id].d))
id = j;
if(!id) { f[l][r] = 0; continue; }
f[l][r] = 0x3f3f3f3f;
for(int k = a[id].l; k <= a[id].r; k++)
f[l][r] = min(f[l][r], f[l][k - 1] + f[k + 1][r] + a[id].d);
}
printf("%d\n", f[1][m]);
}

int main()
{
scanf("%d", &T);
while(T--) solve();
return 0;
}